package com.yonyou.brigade.third_parties.smectrip.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yonyou.brigade.basic_init.enums.ChannelEnum;
import com.yonyou.brigade.basic_init.model.BriChannel;
import com.yonyou.brigade.basic_init.service.IBriChannelService;
import com.yonyou.brigade.order_center.service.IBriOrderService;
import com.yonyou.brigade.third_parties.smectrip.constants.SmeCtripConstants;
import com.yonyou.brigade.third_parties.smectrip.service.ICtripSmeOrderService;
import com.yonyou.brigade.third_parties.smectrip.util.SmeCtripUtil;
import com.yonyou.brigade.util.resultutil.HttpSendUtils;
import com.yonyou.brigade.ybz.service.IConvertService;
import com.yonyou.ybzboot.starter.common.exception.BusinessException;
import com.yonyou.ybzboot.starter.common.util.StringUtil;
import com.yonyou.ybzboot.starter.mongodb.dao.IMongoDao;
import com.yonyou.ybzboot.starter.mongodb.model.CriteriaMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.*;


/**
 * Created by Administrator on 2018/12/29.
 */
@Service
public class CtripSmeOrderServiceImpl implements ICtripSmeOrderService{
    private static final Logger logger = LoggerFactory.getLogger(CtripSmeOrderServiceImpl.class);
    @Autowired
    @Qualifier("briChannelServiceImpl")
    private IBriChannelService briChannelService;

    @Autowired
    @Qualifier("convertServiceImpl")
    private IConvertService convertService;

    @Autowired
    @Qualifier("briOrderServiceImpl")
    private IBriOrderService briOrderService;

    @Autowired
    private SmeCtripUtil smeCtripUtil;

    @Value("${smectrip.url}")
    private  String URL;

    @Value("${smectrip.tradeFlightType}")
    private String ctripSmeFlightTradeType;

    @Value("${smectrip.tradeTrainType}")
    private String ctripSmeTrainTradeType;

    @Value("${smectrip.tradeHotelType}")
    private String ctripSmeHotelTradeType;

    @Value("${cnv.baigade.system.code}")
    private String systemCode;

    @Value("${cnv.register.userId}")
    private String cnvRegisterUserId;

    @Value("${cnv.register.tenant}")
    private String cnvRegisterTenant;

    @Value("${cnv.register.cookie}")
    private String cnvRegisterCookie;

    @Autowired
    private IMongoDao mongoDao;

    // 根据订单号查询携程数据事的最大订单数 防止查询超时
    private final static int maxQueryNum = 30;

    @Override
    public void getCtripSmeOrderList(String tenant, String dateFrom, String dateTo) {

        List<BriChannel> ctripSmeList = briChannelService.getEnableChannelByTenantAndChannel(tenant, "ctripSME");

        if(ctripSmeList==null || ctripSmeList.size()==0) {
            //没有开通携程商旅通
            throw new BusinessException("没有开通携程商旅通");
        }

        String appKey = null;
        String appSecurity = null;
        String ticket = null;

        JSONObject jsonObject = JSON.parseObject(ctripSmeList.get(0).getConfig());
        if (jsonObject != null){
            appKey = jsonObject.getString("appKey");
            appSecurity = jsonObject.getString("appSecurity");
            ticket = smeCtripUtil.getSearchOrderTicket(tenant,appKey,appSecurity);
        }

        JSONObject paramJson = new JSONObject();
        JSONObject authJson = new JSONObject();
        authJson.put("AppKey",appKey);
        authJson.put("Ticket",ticket);
        paramJson.put("Auth",authJson);

        paramJson.put("DateFrom",dateFrom);
        paramJson.put("DateTo",dateTo);

        logger.info("携程商旅通拉单，请求参数->" + paramJson.toJSONString());
        String respStr = HttpSendUtils.sendPost(URL + SmeCtripConstants.SERACHORDER_ACTION_URL,paramJson.toJSONString());
        logger.info("携程商旅通拉单，返回参数->" + respStr);

        JSONObject respJson = null;
        try {
            respJson = JSON.parseObject(respStr);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BusinessException("拉单失败！");
        }

        JSONObject statusJson = respJson.getJSONObject("Status");
        boolean success = statusJson.getBoolean("Success");
        if (!success){
            String message = statusJson.getString("Message");
            logger.error("sme订单取数失败->" + message);
            throw new BusinessException("sme订单取数失败");
        }

        //如果拉单成功，则处理订单数据，生成记事等等
        JSONArray jsonArray = respJson.getJSONArray("ItineraryList");
        if (jsonArray != null && jsonArray.size() > 0){
            for (int i = 0;i < jsonArray.size(); i++){
                doCtripProcessor(jsonArray.getJSONObject(i),tenant,ctripSmeList.get(0).getId());
            }
        }
    }

    /**
     * @param searchType    产品类别 1：机票、酒店、火车票、用车、马上用车 2：机票 3：火车票 4：酒店 5：用车（包含老版国内接送机、国际接送机、国内租车） 6：马上用车 7：新版国内接送机 8：国内包车
     * @param orderIdList 订单号
     * @param tenant 租户ID
     * @description: 按照订单号和产品类别拉取并保存或更新订单
     * @since 2019-02-26
     */
    @Override
    public void getCtripSmeOrderListByOrderId(String searchType, List<String> orderIdList, String tenant) {
        // 每次最多查询30条避免超时
        int updateLength = orderIdList.size();
        int m = 0;
        while (updateLength > maxQueryNum) {
            String orderIds = String.join(",", orderIdList.subList(m, m + maxQueryNum));
            getOrUpdateOrdersByOrderId(searchType, orderIds, tenant);
            m = m + maxQueryNum;
            updateLength = updateLength - maxQueryNum;
        }
        if (updateLength > 0) {
            String orderIds = String.join(",", orderIdList.subList(m, m + updateLength));
            getOrUpdateOrdersByOrderId(searchType, orderIds, tenant);
        }
    }

    private void getOrUpdateOrdersByOrderId(String searchType, String orderIds, String tenant){
        List<BriChannel> ctripSmeList = briChannelService.getEnableChannelByTenantAndChannel(tenant, "ctripSME");

        if(ctripSmeList==null || ctripSmeList.size()==0) {
            //没有开通携程商旅通
            throw new BusinessException("没有开通携程商旅通");
        }

        String appKey = null;
        String appSecurity = null;
        String ticket = null;

        JSONObject jsonObject = JSON.parseObject(ctripSmeList.get(0).getConfig());
        if (jsonObject != null){
            appKey = jsonObject.getString("appKey");
            appSecurity = jsonObject.getString("appSecurity");
            ticket = smeCtripUtil.getSearchOrderTicket(tenant,appKey,appSecurity);
        }

        JSONObject paramJson = new JSONObject();
        JSONObject authJson = new JSONObject();
        authJson.put("AppKey",appKey);
        authJson.put("Ticket",ticket);
        paramJson.put("Auth",authJson);

        paramJson.put("OrderID",orderIds);
        paramJson.put("SearchType",searchType);
        logger.info("携程商旅通拉单，请求参数->" + paramJson.toJSONString());
        String respStr = HttpSendUtils.sendPost(URL + SmeCtripConstants.SERACHORDER_ACTION_URL,paramJson.toJSONString());
        logger.info("携程商旅通拉单，返回参数->" + respStr);

        JSONObject respJson = null;
        try {
            respJson = JSON.parseObject(respStr);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BusinessException("拉单失败！");
        }

        JSONObject statusJson = respJson.getJSONObject("Status");
        boolean success = statusJson.getBoolean("Success");
        if (!success){
            String message = statusJson.getString("Message");
            logger.error("sme订单取数失败->" + message);
            throw new BusinessException("sme订单取数失败");
        }

        //如果拉单成功，则处理订单数据，生成记事等等
        JSONArray jsonArray = respJson.getJSONArray("ItineraryList");
        if (jsonArray != null && jsonArray.size() > 0){
            for (int i = 0;i < jsonArray.size(); i++){
                doCtripProcessor(jsonArray.getJSONObject(i),tenant,ctripSmeList.get(0).getId());
            }
        }
    }

    /**
     * 解析订单 沿用之前的代码
     * @param itineraryJson
     */
    private void doCtripProcessor(JSONObject itineraryJson,String tenant,int channelId){
        JSONObject res = null;

        //酒店订单处理
        JSONArray hotelOrderInfoArr = itineraryJson.getJSONArray("HotelOrderInfoList");
        if(null != hotelOrderInfoArr){
            for (int i = 0; i < hotelOrderInfoArr.size(); i++) {
                JSONObject hotelOrder = hotelOrderInfoArr.getJSONObject(i);
                String orderStatus = hotelOrder.getString("OrderStatus");
                if("未提交".equals(orderStatus) || "已取消".equals(orderStatus)){
                    continue;
                }
                hotelOrder.put("fromSource", ChannelEnum.CTRIPSME.getName());
                dealWithMongo("hotel", hotelOrder.getString("OrderID"), SmeCtripConstants.HOTEL_MONGO_ORDER_TABLENAME, hotelOrder);
                res = convertService.convert(ctripSmeHotelTradeType, systemCode, cnvRegisterUserId, cnvRegisterTenant, cnvRegisterCookie, hotelOrder);

                if (res.getBoolean("success")) {
                    JSONArray results = res.getJSONArray("result");
                    if (results != null && results.size() > 0) {
                        for (int j = 0; j < results.size(); j++) {
                            JSONObject jsonObject = results.getJSONObject(j);
                            JSONObject orderCenter = JSON.parseObject(jsonObject.getString("data"));
                            if (orderCenter != null) {
                                try {
                                    briOrderService.saveHotel(orderCenter, orderCenter.getString("orderNo"), tenant, orderCenter.getString("userId"), ChannelEnum.CTRIPSME.getName(), channelId);
                                } catch (ParseException e) {
                                    logger.error("保存携程商旅通酒店订单时，日期类型转换出现错误",e.getMessage());
                                }
                            }
                        }
                    }
                }
            }
        }

        //飞机订单处理
        JSONArray flightOrderInfoArr = itineraryJson.getJSONArray("FlightOrderInfoList");
        if(null != flightOrderInfoArr){
            for (int i = 0; i < flightOrderInfoArr.size(); i++) {
                JSONObject flightOrder = flightOrderInfoArr.getJSONObject(i);
                flightOrder.put("fromSource", ChannelEnum.CTRIPSME.getName());
                dealWithMongo("flight", flightOrder.getJSONObject("BasicInfo").getString("OrderID"), SmeCtripConstants.FLIGHT_MONGO_ORDER_TABLENAME, flightOrder);
                res = convertService.convert(ctripSmeFlightTradeType, systemCode, cnvRegisterUserId, cnvRegisterTenant, cnvRegisterCookie, flightOrder);

                if (res.getBoolean("success")) {
                    JSONArray results = res.getJSONArray("result");
                    if (results != null && results.size() > 0) {
                        for (int j = 0; j < results.size(); j++) {
                            JSONObject jsonObject = results.getJSONObject(j);
                            JSONObject orderCenter = JSON.parseObject(jsonObject.getString("data"));
                            if (orderCenter != null) {
                                try {
                                    briOrderService.saveFlight(orderCenter, orderCenter.getString("orderNo"), tenant, orderCenter.getString("userId"), ChannelEnum.CTRIPSME.getName(), channelId);
                                } catch (ParseException e) {
                                    logger.error("保存携程商旅通飞机订单时，日期类型转换出现错误",e.getMessage());
                                }
                            }
                        }
                    }
                }
            }
        }


        //火车订单处理
        JSONArray trainOrderInfoArr = itineraryJson.getJSONArray("TrainOrderInfoList");
        if(null != trainOrderInfoArr){
            for (int i = 0; i < trainOrderInfoArr.size(); i++) {
                JSONObject trainOrder = trainOrderInfoArr.getJSONObject(i);
                trainOrder.put("fromSource", ChannelEnum.CTRIPSME.getName());
                dealWithMongo("train", trainOrder.getJSONObject("BasicInfo").getString("OrderID"), SmeCtripConstants.TRAIN_MONGO_ORDER_TABLENAME, trainOrder);
                res = convertService.convert(ctripSmeTrainTradeType, systemCode, cnvRegisterUserId, cnvRegisterTenant, cnvRegisterCookie, trainOrder);

                if (res.getBoolean("success")) {
                    JSONArray results = res.getJSONArray("result");
                    if (results != null && results.size() > 0) {
                        for (int j = 0; j < results.size(); j++) {
                            JSONObject jsonObject = results.getJSONObject(j);
                            JSONObject orderCenter = JSON.parseObject(jsonObject.getString("data"));
                            if (orderCenter != null) {
                                try {
                                    briOrderService.saveTrain(orderCenter, orderCenter.getString("orderNo"), tenant, orderCenter.getString("userId"), ChannelEnum.CTRIPSME.getName(), channelId);
                                } catch (Exception e) {
                                    logger.error("保存携程商旅通火车订单时，日期类型转换出现错误",e.getMessage());
                                }
                            }
                        }
                    }
                }
            }
        }

    }

    private void dealWithMongo(String type, String orderId, String mongoName, JSONObject orderJson) {
        CriteriaMap criteriaMap = new CriteriaMap();
        if ("hotel".equals(type)) {
            criteriaMap.put("OrderID",orderId);
        } else if ("flight".equals(type) || "train".equals(type)) {
            criteriaMap.put("BasicInfo.OrderID",orderId);
        }
        List<JSONObject> ordersources = mongoDao.findByMap(criteriaMap, JSONObject.class, mongoName);
        if(ordersources != null && ordersources.size() > 0) {
            mongoDao.deleteByMap(criteriaMap, mongoName);
            mongoDao.getMongoTemplate().save(orderJson, mongoName);
        }
        else {
            mongoDao.getMongoTemplate().insert(orderJson, mongoName);
        }
    }

}